package com.example.demo.component.zibbix;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.component.others.ThreadPoolFactory;
import com.example.demo.component.zibbix.bean.zibbix_agent;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * @ClassName zibbix_client
 * @Description
 * @date 2022/11/10 15:51
 * @Author yanceysong
 * @Version 1.0
 */
//文档：https://www.zabbix.com/documentation/5.0/zh/manual/api/reference/host/get
public class zibbix_client {

    private final String USERNAME;
    private final String PASSWORD;
    private final String URL;
    private String AUTH = null;

    public zibbix_client(String zabbix_server_ip, String username, String password) {
        this.URL = "http://" + zabbix_server_ip + "/zabbix/api_jsonrpc.php";
        this.USERNAME = username;
        this.PASSWORD = password;
        this.set_auth();
    }

    /**
     * 获取固定分钟内监控数据
     *
     * @param ip                   机器ip
     * @param zibbix_monitor_items 监测类型
     * @param minutes              固定时间戳
     * @return 监控数据
     */
    public JSONArray get_monitor(String ip, zibbix_monitor_items zibbix_monitor_items, Integer minutes) {
        //获取hostId
        String hostId = get_host_id_by_ip(ip);
        //包含监控项的itemId
        String itemId = get_item_id(hostId, zibbix_monitor_items.key);
        //值的类型 浮点数还是整数
        int valueType = get_value_type(hostId, zibbix_monitor_items.key);
        return get_history_data_by_item_id(itemId, valueType, get_time_before(minutes), new Date().getTime());
    }

    /**
     * 获取固定分钟内监控数据
     *
     * @param zibbix_agent         实体机器
     * @param zibbix_monitor_items 监测类型
     * @param minutes              固定时间戳
     * @return 监控数据
     */
    public JSONArray get_monitor(zibbix_agent zibbix_agent, zibbix_monitor_items zibbix_monitor_items, Integer minutes) {
        //包含监控项的itemId
        String itemId = get_item_id(zibbix_agent.getHost_id(), zibbix_monitor_items.key);
        //值的类型 浮点数还是整数
        int valueType = get_value_type(zibbix_agent.getHost_id(), zibbix_monitor_items.key);
        return get_history_data_by_item_id(itemId, valueType, get_time_before(minutes), new Date().getTime());
    }

    /**
     * 获取固定分钟内监控数据
     *
     * @param zibbix_agent         实体机器
     * @param zibbix_monitor_items 监测类型
     * @return 监控数据
     */
    public JSONArray get_monitor(zibbix_agent zibbix_agent, zibbix_monitor_items zibbix_monitor_items) {
        return get_monitor(zibbix_agent, zibbix_monitor_items, 5);
    }

    /**
     * 获取一个主机下面多个监控项的数据
     *
     * @param zibbix_agent         主机
     * @param zibbix_monitor_items 监控项
     * @return 主机对应的监控项
     */
    public Map<zibbix_monitor_items, JSONArray> get_monitor(zibbix_agent zibbix_agent, List<zibbix_monitor_items> zibbix_monitor_items) throws ExecutionException, InterruptedException {
        ExecutorService threadPool = ThreadPoolFactory.getThreadPool();
        ThreadPoolFactory.initThreadPool();
        HashMap<zibbix_monitor_items, JSONArray> result = new HashMap<>();
        HashMap<zibbix_monitor_items, Future<?>> result_futures = new HashMap<>();
        for (zibbix_monitor_items items : zibbix_monitor_items) {
            result_futures.put(items, threadPool.submit(() -> {
            }));
        }
        for (com.example.demo.component.zibbix.zibbix_monitor_items next : result_futures.keySet()) {
            result.put(next, (JSONArray) result_futures.get(next).get());
        }
        return result;
    }

    /**
     * 获取5分钟内监控数据
     *
     * @param ip                   机器ip
     * @param zibbix_monitor_items 监测类型
     * @return 监控数据
     */
    public JSONArray get_monitor(String ip, zibbix_monitor_items zibbix_monitor_items) {
        return get_monitor(ip, zibbix_monitor_items, 5);
    }

    /**
     * 获取前多少分钟的毫秒值
     *
     * @param minutes 多少分钟
     * @return 毫秒值
     */
    private long get_time_before(Integer minutes) {
        return new Date().getTime() - minutes * 60000;
    }

    /**
     * 向Zabbix发送Post请求，并返回json格式字符串
     *
     * @param map 请求参数
     * @return 请求结果
     */
    private String send_post(Map map) {
        String param = JSON.toJSONString(map);
        HttpURLConnection connection = null;
        DataOutputStream out = null;
        BufferedReader reader = null;
        StringBuilder sb = null;
        try {
            //创建连接
            java.net.URL url = new URL(URL);
            connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式
            connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式
            connection.connect();
            //POST请求
            out = new DataOutputStream(connection.getOutputStream());
            out.writeBytes(param);
            out.flush();
            //读取响应
            connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String lines;
            sb = new StringBuilder();
            while ((lines = reader.readLine()) != null) {
                lines = new String(lines.getBytes(), StandardCharsets.UTF_8);
                sb.append(lines);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return sb.toString();
    }

    /**
     * 通过用户名和密码设置AUTH，获得权限
     */
    private void set_auth() {
        Map<String, Object> params = new HashMap<>();
        params.put("user", USERNAME);
        params.put("password", PASSWORD);
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
        map.put("method", "user.login");
        map.put("params", params);
        map.put("auth", null);
        map.put("id", 0);
        String response = send_post(map);
        JSONObject json = JSON.parseObject(response);
        AUTH = json.getString("result");
    }

    /**
     * 获取访问令牌
     *
     * @return 访问令牌
     */
    private String get_auth() {
        if (AUTH == null) {
            set_auth();
        }
        return AUTH;
    }

    /**
     * 获得主机host_id
     *
     * @param hostname Zabbix中配置的主机hosts
     * @return 返回host_id
     */
    private String get_host_id_by_host_name(String hostname) {
        Map<String, Object> filter = new HashMap<>();
        filter.put("host", hostname);
        Map<String, Object> params = new HashMap<>();
        params.put("output", "hostid");
        params.put("filter", filter);
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
        map.put("method", "host.get");
        map.put("params", params);
        map.put("auth", get_auth());
        map.put("id", 0);
        String response = send_post(map);
        JSONArray result = JSON.parseObject(response).getJSONArray("result");
        if (result.size() > 0) {
            JSONObject json = result.getJSONObject(0);
            return json.getString("hostid");
        } else {
            return null;
        }
    }

    /**
     * 获得告警主机所有的主机
     *
     * @return 返回host_id
     */
    public List<zibbix_agent> get_host_with_event() {
         int[] event=new int[]{1,2,3,4,5};
        List<zibbix_agent> results = new ArrayList<>();
        Map<String, Object> params = new HashMap<>();
        params.put("output", "extend");
        params.put("severities", event);
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
//        map.put("severities", String.valueOf(level));
        map.put("method", "host.get");
        map.put("params", params);
        map.put("auth", get_auth());
        map.put("id", 0);
        String response = send_post(map);
        JSONArray result_array = JSON.parseObject(response).getJSONArray("result");
        if (result_array.size() > 0) {
            for (int i = 0; i < result_array.size(); i++) {
                results.add(json2bean(result_array.getJSONObject(i)));
            }
        } else {
            return null;
        }
        return results;
    }

    /**
     * 获取所有主机
     *
     * @return 获取所有的主机
     */
    public List<zibbix_agent> get_all_host() {
        List<zibbix_agent> results = new ArrayList<>();
        Map<String, Object> params = new HashMap<>();
        params.put("output", "extend");
//        params.put("selectInterfaces","ip");
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
        map.put("method", "host.get");
        map.put("params", params);
        map.put("auth", get_auth());
        map.put("id", 0);
        String response = send_post(map);
        JSONArray result_array = JSON.parseObject(response).getJSONArray("result");
        if (result_array.size() > 0) {
            for (int i = 0; i < result_array.size(); i++) {
                results.add(json2bean(result_array.getJSONObject(i)));
            }
        } else {
            return null;
        }
        return results;
    }

    /**
     * 得到的json转实体bean
     *
     * @param jsonObject json
     * @return bean
     */
    private zibbix_agent json2bean(JSONObject jsonObject) {
        zibbix_agent zibbix_agent = new zibbix_agent();
        zibbix_agent.setHost((String) jsonObject.get("host"));
        zibbix_agent.setHost_id((String) jsonObject.get("hostid"));
        zibbix_agent.setName((String) jsonObject.get("name"));
        return zibbix_agent;
    }

    /**
     * 获得主机host_id
     *
     * @param ip Zabbix中配置的主机ip
     * @return 返回host_id
     */
    private String get_host_id_by_ip(String ip) {
        Map<String, Object> filter = new HashMap<>();
        filter.put("ip", ip);
        Map<String, Object> params = new HashMap<>();
        params.put("output", "extend");
        params.put("filter", filter);
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
        map.put("method", "host.get");
        map.put("params", params);
        map.put("auth", get_auth());
        map.put("id", 0);
        String response = send_post(map);
        JSONArray result = JSON.parseObject(response).getJSONArray("result");
        if (result.size() > 0) {
            JSONObject json = result.getJSONObject(0);
            return json.getString("hostid");
        } else {
            return null;
        }
    }

    /**
     * 获得某主机的某个监控项id
     *
     * @param hostId 主机
     * @param key    监控项
     * @return 监控项item_id
     */
    private String get_item_id(String hostId, String key) {
        JSONArray result = get_item_by_host_and_key(hostId, key);
        if (result.size() > 0) {
            JSONObject json = result.getJSONObject(0);
            if (json != null) {
                return json.getString("itemid");
            }
        }
        return null;
    }

    /**
     * 获取某主机某监控项的value_type
     *
     * @param hostId host的id
     * @param key    监控项的key
     * @return 结果
     */
    private int get_value_type(String hostId, String key) {
        JSONArray result = get_item_by_host_and_key(hostId, key);
        if (result.size() > 0) {
            JSONObject json = result.getJSONObject(0);
            if (json != null) {
                return json.getIntValue("value_type");
            }
        }
        return 3;
    }


    /**
     * 获取某主机某监控项在一段时间内的数据
     *
     * @param itemId    监控项item_id
     * @param valueType 返回值的类型
     * @param from      时间戳开始时间
     * @param to        时间戳的结束时间
     * @return 检测结果
     */
    private JSONArray get_history_data_by_item_id(String itemId, int valueType, long from, long to) {
        Map<String, Object> params = new HashMap<>();
        params.put("output", "extend");
        params.put("history", valueType);
        params.put("itemids", itemId);
        params.put("sortfield", "clock");
        params.put("sortorder", "DESC");//时间降序
        params.put("time_from", from / 1000);
        params.put("time_till", to / 1000);
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
        map.put("method", "history.get");
        map.put("params", params);
        map.put("auth", get_auth());
        map.put("id", 0);
        String response = send_post(map);
        return JSON.parseObject(response).getJSONArray("result");
    }


    /**
     * 获取某主机某监控项最近的数据
     *
     * @param hostId host的id
     * @param key    监控项
     * @return 结果
     */
    private JSONArray get_item_by_host_and_key(String hostId, String key) {
        if (hostId == null) {
            return null;
        }
        Map<String, Object> search = new HashMap<>();
        search.put("key_", key);
        Map<String, Object> params = new HashMap<>();
        params.put("output", "extend");
        params.put("hostids", hostId);
        params.put("search", search);
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
        map.put("method", "item.get");
        map.put("params", params);
        map.put("auth", get_auth());
        map.put("id", 0);
        String response = send_post(map);
        return JSON.parseObject(response).getJSONArray("result");
    }


    /**
     * 多个监控项的当前数据
     *
     * @param itemIds 监控项的item_ids
     * @return 监控数据结果
     */
    private JSONArray get_data_by_items(List<String> itemIds) {
        Map<String, Object> params = new HashMap<>();
        params.put("output", "extend");
        params.put("itemids", itemIds);
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
        map.put("method", "item.get");
        map.put("params", params);
        map.put("auth", get_auth());
        map.put("id", 0);
        String response = send_post(map);
        return JSON.parseObject(response).getJSONArray("result");

    }

    /**
     * 多个监控项的历史数据
     *
     * @param itemIds   监控项的item_ids
     * @param valueType 返回值的类型
     * @param from      时间戳开始时间
     * @param to        时间戳的结束时间
     * @return 数据结果
     */
    private JSONArray get_history_data_by_items(List<String> itemIds, int valueType, long from, long to) {
        Map<String, Object> params = new HashMap<>();
        params.put("output", "extend");
        params.put("history", valueType);
        params.put("itemids", itemIds);
        params.put("sortfield", "clock");
        params.put("sortorder", "DESC");//时间降序
        params.put("time_from", from / 1000);
        params.put("time_till", to / 1000);
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
        map.put("method", "history.get");
        map.put("params", params);
        map.put("auth", get_auth());
        map.put("id", 0);
        String response = send_post(map);
        return JSON.parseObject(response).getJSONArray("result");
    }

    /**
     * 获得api版本
     *
     * @return 返回版本
     */
    public String get_api_version() {
        Map<String, Object> map = new HashMap<>();
        map.put("jsonrpc", "2.0");
        map.put("method", "apiinfo.version");
        map.put("params", new ArrayList<>());
        map.put("auth", null);
        map.put("id", 0);
        String response = send_post(map);
        JSONObject result = JSON.parseObject(response);
        return result.getString("result");
    }
}
